package org.itrip.dao;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class Downloader {
	
	private volatile static HttpClient client = null;
	private static final int RETRY_TIMES = 3;
	
	public static void main(String[] args) {
		//String html = getHtml("http://tuniu.com/yii.php?r=detail%2FtourV3Ajax%2Fcalendar&id=210045870&backCityCode=200&departCityCode=200&refreshFileCache=0");
//		String html = getHtml("http://ip.chinaz.com/getip.aspx");

		String html = "1|2|3";


		System.out.println(html.replaceAll("\\|", "p"));
	}
	
	public static String getHtml(String url){
		return getHtml("get", url, null, "UTF-8");
		
	}

	public static String getHtml(String method,String url,Map<String,String> parameters,String charset){
		if(client == null) {
			synchronized (Downloader.class) {
				if(client == null) {
					buildHttpClient();
				}
			}
		}
		
		HttpUriRequest _request = getRequest("GET",url,null,charset);
		HttpResponse _response = retryRequest(_request,RETRY_TIMES);
		if(_response == null) {
			return "";
		}
		byte[] contentBytes;
		try {
			contentBytes = getBytesFromInputStream(_response.getEntity().getContent());
			_request.abort();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		String content = "";
		try {
			content = new String(contentBytes,charset);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return "";
		}		
		return content;
	}
	
	
	private static void buildHttpClient(){
		HttpClientBuilder httpClientBuilder = HttpClients.custom();
		SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).setTcpNoDelay(true).build();
		httpClientBuilder.setDefaultSocketConfig(socketConfig).setUserAgent("Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11 QIHU 360EE");
		PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
		manager.setMaxTotal(200);
		manager.setDefaultMaxPerRoute(20);
		manager.closeIdleConnections(100,TimeUnit.SECONDS);
		httpClientBuilder.setConnectionManager(manager);
		client = httpClientBuilder.build();
	}
	
	public static HttpUriRequest getRequest(String method,String url,Map<String,String> parameters,String charset){
		RequestBuilder  requestBuilder = RequestBuilder.create(method).setCharset(Charset.forName(charset)).setUri(url);
		RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
			.setConnectionRequestTimeout(3000)
			.setSocketTimeout(3000)
			.setConnectTimeout(3000)
			.setCookieSpec(CookieSpecs.DEFAULT);
		requestBuilder.setConfig(requestConfigBuilder.build());
		
		if(parameters != null) {
			for(Map.Entry<String, String> parameter : parameters.entrySet()){
				requestBuilder.addParameter(parameter.getKey(), parameter.getValue());
			}
		}
		return requestBuilder.build();
	}
	
	private static HttpResponse retryRequest(HttpUriRequest request,int times){
		while(times >= 1){
			try {
				HttpResponse response = client.execute(request);
				return response;
			} catch (Exception e) {
				times --;
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
		return null;
	}
	
	private static  byte[] getBytesFromInputStream(InputStream in) throws IOException{
		ByteBuffer buffer = ByteBuffer.allocate(10 * 1024 * 1024);
		byte[] tmp = new byte[5 * 1024];
		int length = 0;
		while((length = in.read(tmp)) > 0){
			buffer.put(tmp, 0, length);
		}
		buffer.flip();
		byte[] result = new byte[buffer.limit()];
		buffer.get(result, 0, buffer.limit());
		return result;
	}
}
